
#include "config/IncludeParts.h"

#if USE_XML

#include "XmlNode.h"
#include "XmlTab.h"
#include "config/Platform.h"
#include "tools/StringManager.h"
#include "config/Def.h"
#include <assert.h>

using namespace unixml;

XmlNode::XmlNode(uint16* code, int32 start):
m_content(0),
m_start(start),
m_end(-1),
m_tab(0),
m_isNode(true),
m_code(code)
{
	checkNode();
	if(m_isNode)
	{
		init();
	}
}

XmlNode::~XmlNode()
{
    uni_delete_array(m_content);
    delete m_tab;
    
    for(int32 i = 0, size = m_children.size(); i < size; ++i)
    {
        delete m_children[i];
    }
}

void XmlNode::checkNode()
{
	int pointer = m_start + 1;
	if(m_code[pointer] == '?')
	{
		m_isNode = false;
		while(pointer != -1)
		{
			pointer = unigame::StringManager::uniFindChar('>', m_code, pointer + 1);
			if(pointer != -1 && m_code[pointer - 1] == '?')
			{
				m_end = pointer + 1;
				return;
			}
		}
		assert(false && "xml node not close with ?>");
	}
	if(m_code[pointer] == '!' && m_code[pointer + 1] == '-' && m_code[pointer + 1] == '-')
	{
		m_isNode = false;
		while(pointer != -1)
		{
			pointer = unigame::StringManager::uniFindChar('>', m_code, pointer + 1);
			if(pointer != -1 && m_code[pointer - 1] == '-' && m_code[pointer - 2] == '-')
			{
				m_end = pointer + 1;
				return;
			}
		}
		assert(false && "xml node not close with -->");
	}
}

void XmlNode::init()
{
    m_tab = uni_new XmlTab(m_code, m_start);
	int32 pointer = unigame::StringManager::uniFindChar('<', m_code, m_tab->getEnd());
    int32 start = m_tab->getEnd();
    int32 end = pointer;
    unigame::StringManager::uniTrimStr(m_code, &start, &end);
    int32 len = end - start;
    if(len > 0)
    {
        m_content = uni_new uint16[len + 1];
        memcpy(m_content, m_code + start, sizeof(uint16) * len);
        m_content[len] = 0;
    }
    while(pointer != -1)
    {
        if(m_code[pointer + 1] == '/')
        {
            int32 temp = pointer + 2;
            pointer = unigame::StringManager::uniFindChar('>', m_code, temp);
            assert(pointer != -1 && "xml node not close");
#if UNI_DEBUG
            int32 len = pointer - temp;
            uint16* endName = uni_new uint16[len + 1];
            memcpy(endName, m_code + temp, len * sizeof(uint16));
			endName[len] = 0;
            assert(unigame::StringManager::uniCompare(endName, m_tab->getName()) == 0 && "xml node not match");
			delete[] endName;
#endif
            m_end = pointer + 1;
            pointer = -1;
        }
        else
        {
            XmlNode* node = uni_new XmlNode(m_code, pointer);
            pointer = node->getEnd();
            if(node->isNode())
            {
                m_children.push_back(node);
            }
            else
            {
                delete node;
            }
        }
    }
}

uint16* XmlNode::getName()
{
    return m_tab->getName();
}

uint16* XmlNode::getAttribute(const uint16 *name)
{
    return m_tab->getAttribute(name);
}

#endif